using System;
using System.Collections;
using System.Data;
using System.Net.Mail;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;
using Utils = PHSRAG.Insight21.InsightUtilities;

namespace PHSRAG.Insight21.COI
{
    /// <summary>
    /// This page will be presented only to the users with suprevisor and/super user access rights.
    /// The search criteria will enable the logged in user with required permission to search for the user any levels down the hierarchy.
    /// The search will yield the summary of the user and the COI matching the criteria.
    /// Note:For the supe-user this page will bring down everybody in the system irrespective of the levels
    /// </summary>
    /// 
    public partial class SupervisorSummary : BasePage
    {
        #region Constants

        private const string AnnunciatorTitle = "The following error(s) occurred...";
        private const string ImpersonatedKey = "impersonated_D9B2FC11-4FB4-47ad-94B2-86CD91550870";
        private const string ImpersonatedSupervisorNameNone = "--Select--";
        private const string KeyField = "Id"; //Id column(Datkey column) for the data source
        private const string SqlReportingParamNameSupervisorName = "supervisorName";
        private const string SqlReportingParamNameXml = "xml";
        private const string SSummaryPageIndexKey = "SSummaryPageIndexKey_D9B2FC11-4FB4-47ad-94B2-86CD91550870";

        #endregion

        #region Private variables

        private ICachePolicy applicationCachePolicy;
        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;
        private int parentId; // Person Id for impersonation.

        #endregion

        #region Protected variables

        protected COISearch coiSearch;
        protected CommonSearch commonSearch;

        #endregion

        #region Events

        /// <summary>
        /// This event will be captured by the base page(Supervisor Summary page)that will be raised by the userimpersonation user control.
        /// </summary>
        public event EventHandler ClearSelectionClicked;

        #endregion

        #region Private Properties

        /// <summary>
        /// Gets the parentId(for whom the results had to be shown in the grid)
        /// </summary>
        private int ParentId
        {
            get
            {
                UserContext userContext = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey));
                return (parentId == 0) ? userContext.PersonId : parentId;
            }
            set { parentId = value; }
        }

        private bool IsLoggedInUserADelegate
        {
            get
            {
                int loggedInUserId = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;
                return COIUserSummary.IsLoggedInUserADelegate(loggedInUserId, DataAccess.GetConnectionString());
            }
        }

        /// <summary>
        /// indicates whether or not a supervisor is impersonated
        /// </summary>
        private bool Impersonated
        {
            get { return (ViewState[ImpersonatedKey] == null) ? false : Convert.ToBoolean(ViewState[ImpersonatedKey]); }
            set { ViewState[ImpersonatedKey] = value; }
        }

        /// <summary> 
        /// Gets the COIUserSummary object relevant to the passed in search criteria.
        /// Functionality description:
        /// -when the logged in user is a super user: Load all the people in the system having access to the COI module irrespective of whether or not they are tied to the hierarchy.
        /// -when the logged in user is a supervisor: Load all the people only under the level he/she is in
        /// Note:If the logged in super-user is impersonated as somebody in supervisor dropdown,irrespective of the user's access rights,he/she will be treataed as a supervisor.
        ///  </summary>
        private COIUserSummary COIUserSummary
        {
            get
            {
                COIUserSummary cOIUserSummary = COIUserSummaryFromCache;
                CommonSearchContext searchContext = (CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey);
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                if (cOIUserSummary == null)
                {
                    cOIUserSummary = new COIUserSummary(cachePolicy);
                }

                UserContext userContext = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey));
                

                if (userContext != null)
                {
                    if ((ParentId == userContext.PersonId) && ((userContext.ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) != 0) && searchCriteria.Keys.Count <= 1)
                    {
                        if ((userContext.ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) != 0)
                        {
                            return null;
                        }
                    }
                    else if (ParentId != userContext.PersonId)
                    {
                        Impersonated = true;
                    }

                    cOIUserSummary.Load(DataAccess.ConnectionString, searchCriteria, ParentId, (int) Constants.SourcePage.SupervisorSummarypage,
                        ((userContext.ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) != 0 && !Impersonated));
                }

                cOIUserSummary.Cache();

                return cOIUserSummary;
            }
        }

        /// <summary>
        /// Get/Set the current page within the datagrid for display. This information persists across page loads.
        /// </summary>
        private int CurrentPageIndex
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SupervisorSummaryPageKey) as Hashtable;
                return (h == null || h[SSummaryPageIndexKey] == null) ? 0 : (int) h[SSummaryPageIndexKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SupervisorSummaryPageKey) as Hashtable ?? new Hashtable();

                h[SSummaryPageIndexKey] = value;
                detailGrid.CurrentPageIndex = value;
                pageCachePolicy.Cache(Keys.SupervisorSummaryPageKey, h);
            }
        }

        /// <summary>
        /// Gets the Cached COIUserSummary object
        /// </summary>
        private COIUserSummary COIUserSummaryFromCache
        {
            get { return cachePolicy.GetCachedObject(COIUserSummary.CacheKey) as COIUserSummary; }
        }

        #endregion

        #region Page Event handlers

        /// <summary>
        /// This  is the custom event raised by the UserImpersonation control.
        /// As the page load action of the user control happens after loading the page,
        /// The base page(containing the user control)has to be reloaded to reflect the changes from the user control.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnImpersonate(object sender, EventArgs e)
        {
            try
            {
                Impersonated = true;
                PerformSearch();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// This  is the custom event raised by the UserImpersonation control.
        /// As the common search criteria is not updated on the Find supervisor click,
        /// the control is made to raise an event which would be captured by the page containing it,
        /// to update the search criteria. 
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnFindSupervisor(object sender, EventArgs e)
        {
            commonSearch = (CommonSearch) helpContainer.FindControl("commonSearch");
            commonSearch.UpdateSearchCriteria();
        }

        /// <summary>
        /// The page load event handler
        /// </summary>
        /// <param name="sender">Sender,that raised the event</param>
        /// <param name="e">arguments related to the sender</param>
        protected void OnPageLoad(object sender, EventArgs e)
        {
            try
            {
                annunciator.Message = string.Empty;
                annunciator.Title = string.Empty;
                breadCrumb.Add("Supervisor Summary", Settings.GetKeyValue("SubNavigation.CoI.SupervisorSummaryURL", string.Empty), Settings.GetKeyValue("BreadCrumb.SummaryPageLevel", 1));
                ShowOrHideImpersonation();
                SetPrivilegeToReviewCOI();
                SetPersonIdToImpersonate();

                

                if (!IsPostBack && postbackGuard.IsValid)
                {
                    downloadBar.ReportHostPage = Settings.GetKeyValue(Common.Constants.ConfigKeyReportHostPageCoi, Settings.GetKeyValue(Common.Constants.ConfigKeyReportHostPage, string.Empty));
                    downloadBar.SQLReportName = SSRSRequest.ReportNames.Coi.SupervisorSummary;

                    detailGrid.PageSize = Settings.GetKeyValue("COIDataGrid.ItemsPerPage", 20);
                    CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;

                    SetPersonIdToImpersonate();

                    UserContext userContext = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey));
                    SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                    if (userContext != null)
                    {
                        if (ParentId == userContext.PersonId)
                        {
                            //if only superuser(no supervisor access)
                            if (
                                ((userContext.ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) != 0 && searchCriteria.Keys.Count <= 1)
                                )
                            {
                                coiSearch = (COISearch)helpContainer.FindControl("coISearch");
                                coiSearch.DefaultHierarchyType = COIUser.HierarchyType.None;
                                return;
                            }
                        }
                        if (CurrentPageIndex == 0)
                        {
                            InitializePager();
                        }
                        LoadDataGrid();
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
            finally
            {
                coiSubNavigation.SelectedLink = "Supervisor Summary";
                coiSubNavigation.AccessLevel = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask;
                coiSubNavigation.IsLoggedInUserADelegate = IsLoggedInUserADelegate;
            }
        }

        /// <summary>
        /// Last change to make changes to controls.  We do this here because ParentId can change
        /// in some page event handlers (like impersonate).  Doing this in page load doesn't give
        /// you the correct data.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            detailedReport.OnClientClick = "javascript:window.open('../Research/DownloadForm.aspx?Report=coidtreport&ParentId=" + ParentId + "&filterByLatestReportingPeriod=true', 'supervisorReport', 'resizable=yes, status=yes, scrollbars=yes');return false;";
            summaryReport.OnClientClick = "javascript:window.open('../Research/DownloadForm.aspx?Report=coisumreport&ParentId=" + ParentId + "&filterByLatestReportingPeriod=true', 'supervisorReport', 'resizable=yes, status=yes, scrollbars=yes');return false;";

            base.OnPreRender(e);
        }

        /// <summary>
        /// Event raised on binding the datasource to the grid
        /// </summary>
        /// <param name="sender">owner of the event</param>
        /// <param name="e">arguments with respect to the event</param>
        private void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if ((e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem))
                {
                    string coiStatus = ((Label) e.Item.Cells[((int) ColumnIndex.COIRefCodeStatus)].Controls[1]).Text.Trim();
                    string coiId = ((DataRowView) e.Item.DataItem).Row.ItemArray[3].ToString();
                    string coiAdmPersonId = ((LinkButton) e.Item.Cells[(int) ColumnIndex.Notify].Controls[1]).CommandArgument;
                    int loggedInPersonid = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;
                    if ((coiStatus != Constants.COIStatus.Start) && (coiStatus != Constants.COIStatus.InProgress) && (coiStatus != Constants.COIStatus.Terminated))
                    {
                        e.Item.Cells[(int) ColumnIndex.PolicyQuestion].Text = (e.Item.Cells[(int) ColumnIndex.PolicyQuestion].Text.ToLower() == "true") ? "*" : "";
                        e.Item.Cells[(int) ColumnIndex.OutsideActivity].Text = (e.Item.Cells[(int) ColumnIndex.OutsideActivity].Text.ToLower() == "true") ? "Y" : (e.Item.Cells[(int) ColumnIndex.OutsideActivity].Text.ToLower() == "false") ? "N" : "";
                        e.Item.Cells[(int) ColumnIndex.OtherActivity].Text = (e.Item.Cells[(int) ColumnIndex.OtherActivity].Text.ToLower() == "true") ? "Y" : (e.Item.Cells[(int) ColumnIndex.OtherActivity].Text.ToLower() == "false") ? "N" : "";
                        e.Item.Cells[(int) ColumnIndex.EquityInterest].Text = (e.Item.Cells[(int) ColumnIndex.EquityInterest].Text.ToLower() == "true") ? "Y" : (e.Item.Cells[(int) ColumnIndex.EquityInterest].Text.ToLower() == "false") ? "N" : "";
                        e.Item.Cells[(int) ColumnIndex.FamilyInterset].Text = (e.Item.Cells[(int) ColumnIndex.FamilyInterset].Text.ToLower() == "true") ? "Y" : (e.Item.Cells[(int) ColumnIndex.FamilyInterset].Text.ToLower() == "false") ? "N" : "";
                        e.Item.Cells[(int) ColumnIndex.Royalty].Text = (e.Item.Cells[(int) ColumnIndex.Royalty].Text.ToLower() == "true") ? "Y" : (e.Item.Cells[(int) ColumnIndex.Royalty].Text.ToLower() == "false") ? "N" : "";
                    }
                    else
                    {
                        e.Item.Cells[(int) ColumnIndex.PolicyQuestion].Text =
                            e.Item.Cells[(int) ColumnIndex.OutsideActivity].Text =
                                e.Item.Cells[(int) ColumnIndex.OtherActivity].Text =
                                    e.Item.Cells[(int) ColumnIndex.EquityInterest].Text =
                                        e.Item.Cells[(int) ColumnIndex.FamilyInterset].Text =
                                            e.Item.Cells[(int) ColumnIndex.Royalty].Text = "";
                    }
                    /*The reviwe checkbox will be displayed only both of the following conditions are satisfied
                     * 1. When the loggedin reviewerId is not the same as the owner of the COI
                     * 2. When the COi status is submitted
                     */
                    (e.Item.Cells[(int) ColumnIndex.ReviewCheckBox].Controls[1]).Visible = (coiStatus == Constants.COIStatus.Submitted && Convert.ToInt32(coiAdmPersonId) != loggedInPersonid) ? true : false;
                    if (coiStatus != string.Empty)
                    {
                        ((LinkButton) e.Item.Cells[((int) ColumnIndex.AddViewNote)].Controls[1]).OnClientClick = "javascript:window.open('AddNote.aspx?COIId=" + coiId + "', 'AddCOI', 'width = 700, height = 550, toolbar = no, resizable=no, status=yes, scrollbars=yes');return false;";
                    }
                    else
                    {
                        (e.Item.Cells[((int) ColumnIndex.AddViewNote)].Controls[1]).Visible = false;
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Event raised on performing actions on the datagrid
        /// </summary>
        /// <param name="sender">owner of the event</param>
        /// <param name="e">arguments with respect to the event</param>
        private void OnItemCommand(object sender, DataGridCommandEventArgs e)
        {
            try
            {
                if (e.CommandName == "COIHistory")
                {
                    Hashtable incomingPageHash = cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;

                    Hashtable outgoingData = new Hashtable();
                    outgoingData.Add(Keys.AdmPersonIdKey, Convert.ToInt32(detailGrid.DataKeys[e.Item.ItemIndex]));
                    outgoingData.Add(Keys.FullNameKey, ((LinkButton) e.Item.Cells[(int) ColumnIndex.Name].Controls[0]).Text.Trim());
                    outgoingData.Add(Keys.ImpersonationIdKey, (incomingPageHash != null && incomingPageHash.ContainsKey(Keys.ImpersonationIdKey)) ? (int) incomingPageHash[Keys.ImpersonationIdKey] : 0);

                    cachePolicy.UnCache(COIUserSummary.CacheKey);
                    cachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                    Response.Redirect(Settings.GetKeyValue("SubNavigation.CoI.COIHistoryURL", ""), false);
                }
                else if (e.CommandName == "Notify")
                {
                    PerformNotification(Convert.ToInt32(detailGrid.DataKeys[e.Item.ItemIndex]));
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Sort event handler
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnSort(object source, DataGridSortCommandEventArgs e)
        {
            try
            {
                if (e.SortExpression != string.Empty)
                {
                    COIUserSummary cOIUserSummary = COIUserSummaryFromCache ?? new COIUserSummary(cachePolicy);

                    cOIUserSummary.SortColumn = e.SortExpression;
                    cOIUserSummary.SortAscending = (cOIUserSummary.SortColumn == e.SortExpression) ? !cOIUserSummary.SortAscending : cOIUserSummary.SortAscending;
                    cOIUserSummary.Cache();
                    LoadDataGrid();
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// This event is raised when the page index property is changed on the pager control.
        /// The page's DataGrid is reloaded with the data belonging to page specified by the index.
        /// </summary>
        /// <param name="source">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnPageIndexChanged(object source, DataGridPageChangedEventArgs e)
        {
            try
            {
                detailGrid.CurrentPageIndex = e.NewPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the FirstPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the first page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnFirstPage(object sender, CommandEventArgs e)
        {
            try
            {
                CurrentPageIndex = 0;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the LastPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the last page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnLastPage(object sender, CommandEventArgs e)
        {
            try
            {
                int lastPageIndex = topPager.PageCount - 1;
                CurrentPageIndex = lastPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the NextPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the next page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnNextPage(object sender, CommandEventArgs e)
        {
            try
            {
                ++CurrentPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Occurs when the PreviousPage hyperlink is clicked on the pager.
        /// The page's DataGrid is reloaded with the data belonging to the previous page.
        /// </summary>
        /// <param name="sender">The object raising an event.</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnPreviousPage(object sender, CommandEventArgs e)
        {
            try
            {
                --CurrentPageIndex;
                LoadDataGrid();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// If the item being created is the data grid header, do the following:
        /// Add the appropriate sort symbol to denote ascending/descending sequence for the current sort column.
        /// This requires us to locate the cell which corresponding to the column within the collection of TableCell
        /// maintained by the DataGridItem which is under creation. That collection is indexed numerically, the value being
        /// the position of the column within the columns collection maintained by the data grid.
        /// One simple way to do this is to create static mapping between the name of the column and its index. However, this
        /// suffers from the shortcoming that if the sequence of columns is changed on the page, the static binding MUST
        /// be changed too. If they get out of sync, we would be sorting on inappropriate columns!
        /// To avoid this, and to render the code independent of how the page gets managed, we will build a Hashtable of
        /// column indeces, keyed by the sort expression of each column. That way, we could do a quick lookup to get the
        /// index of a column and set the sort symbol on that column.
        /// If the item being created is a data row item, disable its view state.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Header)
                {
                    COIUserSummary cOIUserSummary = COIUserSummaryFromCache;
                    Label sortSymbol = new Label();
                    sortSymbol.Text = (cOIUserSummary.SortAscending) ? InsightUtilities.Constants.SortAscendingText : InsightUtilities.Constants.SortDescendingText;
                    sortSymbol.Font.Name = InsightUtilities.Constants.SortSymbolFontName;

                    Hashtable columnMap = new Hashtable();
                    foreach (DataGridColumn column in detailGrid.Columns)
                    {
                        columnMap[column.SortExpression] = detailGrid.Columns.IndexOf(column);
                    }

                    string sortColumn = cOIUserSummary.SortColumn;
                    if (columnMap.ContainsKey(sortColumn))
                    {
                        (e.Item.Cells[(int) columnMap[sortColumn]]).Controls.Add(sortSymbol);
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header changes/breadcrumb navigation.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                PurgeCache();
                coiSubNavigation.Reset();
                RemovePersonIdFromIncomingCache();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Purges the cache before the COI subnavigation header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnSubNavigate(object sender, CommandEventArgs e)
        {
            try
            {
                PurgeCache();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Invoked by the download bar when it catches an exception.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnDownloadFailed(object sender, CommandEventArgs e)
        {
            try
            {
                annunciator.Title = "Following error(s) occurred while downloading";
                annunciator.Message = ExceptionReport.GetExceptionInfo((Exception) e.CommandArgument, false);
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Update the review date for all the matching records obtained from search.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnReview(object sender, ImageClickEventArgs e)
        {
            try
            {
                COIUserSummary cOIUserSummary = COIUserSummaryFromCache;

                if (cOIUserSummary != null)
                {
                    cOIUserSummary.UpdateReviewDate(DataAccess.ConnectionString, ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId);
                    PerformSearch();
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Update the review date for all the matching records obtained from search.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OnReviewSelected(object sender, ImageClickEventArgs e)
        {
            try
            {
                ArrayList selectedCOIsforReview = new ArrayList();
                foreach (DataGridItem item in detailGrid.Items)
                {
                    if ((item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
                        && ((CheckBox) (item.Cells[(int) ColumnIndex.ReviewCheckBox]).Controls[1]).Checked)
                    {
                        if (((Label) (item.Cells[(int) ColumnIndex.COIId]).Controls[1]).Text != string.Empty)
                        {
                            selectedCOIsforReview.Add(((Label) (item.Cells[(int) ColumnIndex.COIId]).Controls[1]).Text);
                        }
                    }
                }
                COIUserSummary cOIUserSummary = COIUserSummaryFromCache;

                if (cOIUserSummary != null)
                {
                    if (selectedCOIsforReview.Count > 0)
                    {
                        cOIUserSummary.UpdateReviewDate(DataAccess.ConnectionString, ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId, selectedCOIsforReview);
                        PerformSearch();
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Search event handler

        /// <summary>
        /// Handler for the event raised by the CommonSearch control when the "Clear Selection" buttion is clicked upon.
        /// The control clears the criteria (specific to this module).
        /// Since in the page life-cycle, the Load occurs before the Clear event, we have to instigate a re-load of the
        /// data grid to refelect the fact that the search criteria has been cleared.
        /// </summary>
        /// <param name="sender">Sender of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            try
            {
                Impersonated = false;
                ParentId = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;
                Hashtable outgoingData = new Hashtable();
                outgoingData.Add(Keys.ImpersonationIdKey, ParentId);
                cachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                //gridContainer.Visible=false;
                SetPersonIdToImpersonate();
                if (ClearSelectionClicked != null)
                {
                    ClearSelectionClicked(sender, e);
                }
                PerformSearch();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        /// <summary>
        /// Initiates the search by calling PerformSearch
        /// </summary>
        /// <param name="args">Argument associated with the event (contains the search criteria dictionary)</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            try
            {
                PerformSearch();
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
        }

        #endregion

        #region Private methods

        /// <summary>
        /// Removes the personId from the incoming cache that was added during the page life cycle.
        /// Note:This method will be called when the page goes out of scope.
        /// </summary>
        private void RemovePersonIdFromIncomingCache()
        {
            Hashtable outgoingData =
                cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            if (outgoingData != null)
            {
                if (outgoingData.ContainsKey(Keys.ImpersonationIdKey))
                {
                    outgoingData.Remove(Keys.ImpersonationIdKey);
                    outgoingData.Add(Keys.ImpersonationIdKey, ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId);
                    pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);
                }
            }
        }

        /// <summary>
        /// The Impersonation is handled using the incoming page cache.
        /// Note: sets the parentId(property variable) to the personID available in incoming cache.
        /// If one does not exist in the incoming cache ,then the logged in user's admPersonId will be set to the parent id.
        /// </summary>
        private void SetPersonIdToImpersonate()
        {
            Hashtable incomingPageHash =
                cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
            ParentId = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).PersonId;

            if (incomingPageHash != null && incomingPageHash.ContainsKey(Keys.ImpersonationIdKey))
            {
                ParentId = Convert.ToInt32(incomingPageHash[Keys.ImpersonationIdKey]);
            }
        }

        /// <summary>
        /// This method will determine whether or not to dispaly the Impersonation control depending on the access rights.
        /// Note:If Logged in User is a Super-User then shows Impersonation control.
        /// </summary>
        private void ShowOrHideImpersonation()
        {
            if (
                (((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int) ModuleRoleBit.SuperUser) != 0
                    || (IsLoggedInUserADelegate)
                )
            {
                impersonationPanel.Visible = true;
            }
        }

        /// <summary>
        /// Uncaches all objects with data for this page.
        /// </summary>
        private void PurgeCache()
        {
            System.Diagnostics.Trace.WriteLine("Purging Supervisor Summary...");
            COIUserSummary coiUserSummary = COIUserSummaryFromCache;
            if (coiUserSummary != null)
            {
                coiUserSummary.Purge();
                cachePolicy.UnCache(COIUserSummary.CacheKey);
            }
        }

        /// <summary>	
        /// Loads the COIUser Summary details only for those to displayed on the page.
        /// </summary>
        private void LoadDataGrid()
        {
            SetPersonIdToImpersonate();
            COIUserSummary cOIUserSummary = COIUserSummary;
            if (cOIUserSummary != null)
            {
                detailGrid.VirtualItemCount = bottomPager.RecordCount =
                    topPager.RecordCount = cOIUserSummary.Count;
                int currentPageIndex = CurrentPageIndex;
                int pageCount = (topPager.RecordCount/detailGrid.PageSize) +
                    (((topPager.RecordCount%detailGrid.PageSize) == 0) ? 0 : 1);
                bottomPager.PageCount = topPager.PageCount = pageCount;
                bottomPager.CurrentPage = topPager.CurrentPage = currentPageIndex + 1;

                DataTable table = cOIUserSummary.GetSummaryList(
                    currentPageIndex*detailGrid.PageSize, detailGrid.PageSize, DataAccess.ConnectionString, (int) Constants.SourcePage.SupervisorSummarypage);
                detailGrid.DataSource = table;
                detailGrid.DataKeyField = KeyField;
                detailGrid.DataBind();

                // Add reporting parameters to session in case this page needs to be downloaded to excel/pdf
                Hashtable sqlReportingParams = new Hashtable();
                sqlReportingParams.Add(SqlReportingParamNameXml, cOIUserSummary.GetDataContainer().GetXml());

                if (!string.IsNullOrEmpty(userImpersonation.SelectedUserName) && (userImpersonation.SelectedUserName != ImpersonatedSupervisorNameNone))
                {
                    sqlReportingParams.Add(SqlReportingParamNameSupervisorName, userImpersonation.SelectedUserName);
                }
                else
                {
                    UserContext uc = ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey));

                    if ((uc.ModuleRoleBitmask & (int) ModuleRoleBit.Supervisor) != 0)
                    {
                        sqlReportingParams.Add(SqlReportingParamNameSupervisorName, uc.LastName + ", " + uc.FirstName);
                    }
                }

                Session[Common.Constants.SessionVarNameSsrsReportParams] = sqlReportingParams;

                if (table.Rows.Count == 0)
                {
                    gridContainer.Visible = false;
                    annunciator.Message = "The search criteria yielded no results.";
                }
                else
                {
                    gridContainer.Visible = true;
                    annunciator.Message = string.Empty;
                    recordCount.Text = topPager.RecordCount.ToString();
                    ManagePagination();
                    ManageNavigationLinks();
                }
            }
            else
            {
                gridContainer.Visible = false;
                annunciator.Message = string.Empty;
            }
        }

        /// <summary>
        /// Initilize the first record, last record and current page values for the pager controls.
        /// Set the current page index to 0 and manage navigation links.
        /// </summary>
        private void InitializePager()
        {
            bottomPager.FirstRecord = topPager.FirstRecord = 1;
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(detailGrid.PageSize, detailGrid.Items.Count);
            bottomPager.CurrentPage = topPager.CurrentPage = 1;
            CurrentPageIndex = 0;
            ManageNavigationLinks();
        }

        /// <summary>
        /// Enables or Disables links to other pages within the grid
        /// </summary>
        private void ManageNavigationLinks()
        {
            bottomPager.EnableFirstPage = topPager.EnableFirstPage =
                bottomPager.EnablePreviousPage = topPager.EnablePreviousPage =
                    (detailGrid.CurrentPageIndex != 0);

            bottomPager.EnableLastPage = topPager.EnableLastPage =
                bottomPager.EnableNextPage = topPager.EnableNextPage =
                    (detailGrid.CurrentPageIndex != (topPager.PageCount - 1));
        }

        /// <summary>
        /// Pagination management
        /// </summary>
        private void ManagePagination()
        {
            int currentPageIndex = CurrentPageIndex;
            detailGrid.CurrentPageIndex = currentPageIndex;

            int startIndex = currentPageIndex*detailGrid.PageSize;
            bottomPager.FirstRecord = topPager.FirstRecord = startIndex + 1;

            int lastRecord = COIUserSummary.Count;
            bottomPager.LastRecord = topPager.LastRecord =
                Math.Min(startIndex + detailGrid.PageSize, lastRecord);
        }

        /// <summary>
        /// Retrieves the CommonSearchContext from the cache and
        /// performs a supervisorSummary search.
        /// </summary>
        private void PerformSearch()
        {
            CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            if (searchContext != null)
            {
                CurrentPageIndex = 0;
                LoadDataGrid();
            }
        }

        /// <summary>
        /// Step:1 Checks the existance of COI('Start','InProgress') for the person to be notified.
        /// Step:2
        /// --if a user has an existing COI with the above status , just update the Date Notified field.
        /// --else, create a new COI for the person and update the Date Notified field.
        /// Step:3
        ///	Send Mail
        /// </summary>
        /// <param name="personId">admPersonId</param>
        private void PerformNotification(int personId)
        {
            try
            {
                ConflictOfInterest cOI;
                DataRow cOIRow = COIUserSummary.GetCOIInProgress(DataAccess.ConnectionString, personId);

                if (cOIRow == null)
                {
                    COICollection.AddNewCOI(cachePolicy, personId, Constants.COIDateType.NotifiedDate,Constants.COIType.AnnualCycle,string.Empty);
                }
                else
                {
                    cOI = new ConflictOfInterest(cachePolicy, cOIRow);
                    cOI.Save(DataAccess.ConnectionString, Constants.COIDateType.NotifiedDate);
                }
                SendMail(personId);
            }
            catch (Exception ex)
            {
                DisplayExceptionReport(ex);
            }
            finally
            {
                //On successfull notification,the grid has to be rebound.
                PerformSearch();
            }
        }

        /// <summary>
        /// Send Notification mail to the user notified
        /// </summary>
        private void SendMail(int personId)
        {
            Person person = new Person(cachePolicy);
            person.Load(DataAccess.ConnectionString, personId);

            if (string.IsNullOrEmpty(person.Email))
            {
                throw new Exception("The person does not have an email id.");
            }

            MailMessage message = new MailMessage(Settings.GetKeyValue("Email.COI.Admin", string.Empty), person.Email);

            RefCodes refCodes = (RefCodes) applicationCachePolicy.GetCachedObject(RefCodes.CacheKey);
            RefCode refCode = refCodes.GetRefCode(Constants.NotificationTypes.Domain, Constants.NotificationTypes.Individual);

            message.Subject = refCode.Meaning;

            COIEMailTemplate emailTemplate = new COIEMailTemplate(cachePolicy);
            emailTemplate.Load(DataAccess.ConnectionString, Constants.NotificationTypes.Individual);
            message.Body = emailTemplate.BodyText;
            message.IsBodyHtml = true;
            SmtpClient client = new SmtpClient(Settings.GetKeyValue("Email.SMTPServer", "127.0.0.1"));
            client.Send(message);
        }

        /// <summary>
        /// This method will determine whether or not to dispaly the Review button depending on the access rights.
        /// Note:If Logged in User is a Super-vser then review button will be disabled.
        /// </summary>
        private void SetPrivilegeToReviewCOI()
        {
            if (
                (((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).ModuleRoleBitmask & (int) ModuleRoleBit.Supervisor) != 0
                    || IsLoggedInUserADelegate)
            {
                setReviewed.Visible = reviewSelected.Visible = true;
            }
        }

        /// <summary>
        /// Displays an error message on the screen to the user with the exception, and all
        /// inner exception messages.
        /// </summary>
        /// <param name="ex">The exception to report on</param>
        private void DisplayExceptionReport(Exception ex)
        {
            annunciator.Title = AnnunciatorTitle;
            annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
        }

        #endregion

        #region Web Form Designer generated code

        protected override void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
            applicationCachePolicy = (Policy.ICachePolicy) Application[Policy.Names.ApplicationCachePolicyKey];

            coiSubNavigation.Navigate += new CommandEventHandler(OnSubNavigate);
            this.downloadBar.FailedAction += new CommandEventHandler(OnDownloadFailed);
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.header.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnNavigate);
            this.breadCrumb.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnNavigate);
            this.topPager.FirstPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnFirstPage);
            this.topPager.PreviousPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnPreviousPage);
            this.topPager.NextPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnNextPage);
            this.topPager.LastPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnLastPage);
            this.detailGrid.ItemCreated += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemCreated);
            this.detailGrid.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnItemCommand);
            this.detailGrid.PageIndexChanged += new System.Web.UI.WebControls.DataGridPageChangedEventHandler(this.OnPageIndexChanged);
            this.detailGrid.SortCommand += new System.Web.UI.WebControls.DataGridSortCommandEventHandler(this.OnSort);
            this.detailGrid.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
            this.bottomPager.FirstPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnFirstPage);
            this.bottomPager.PreviousPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnPreviousPage);
            this.bottomPager.NextPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnNextPage);
            this.bottomPager.LastPage += new System.Web.UI.WebControls.CommandEventHandler(this.OnLastPage);
            this.setReviewed.Click += new ImageClickEventHandler(OnReview);
            //this.detailedReport.Click += new ImageClickEventHandler(OnDetailedReport);
            //this.summaryReport.Click += new ImageClickEventHandler(OnSummaryReport);
            this.Load += new System.EventHandler(this.OnPageLoad);
            this.userImpersonation.ImpersonateClicked += new EventHandler(OnImpersonate);
            this.ClearSelectionClicked += new EventHandler(this.userImpersonation.ResetDropDownSelection);
            this.userImpersonation.FindSupervisorsClicked += new EventHandler(OnFindSupervisor);
        }

        #endregion

        #region Enums

        /// <summary>
        /// Provides indexes used in the datagrid for specific columns
        /// </summary>
        private enum ColumnIndex
        {
            /// <summary>LastReviewed column index</summary>
            ReviewCheckBox,
            /// <summary>COIId column index (hidden)</summary>
            COIId,
            /// <summary>Name column index (hidden)</summary>
            Name,
            /// <summary>Supervisor column index (hidden)</summary>
            Supervisor,
            /// <summary>PolicyQuestion column index (hidden)</summary>
            PolicyQuestion,
            /// <summary>OutsideActivity column index (hidden)</summary>
            OutsideActivity,
            ///<summary>EquityInterest column index</summary>
            EquityInterest,
            /// <summary>FamilyInterest column index</summary>
            FamilyInterset,
            /// <summary>OtherActivity column index</summary>
            OtherActivity,
            /// <summary>Royalty(IP Payment) column index</summary>
            Royalty,
            /// <summary>LastSubmitted column index</summary>
            LastSubmitted,
            /// <summary>LastReviewed column index</summary>
            LastReviewed,
            /// <summary>COI status column </summary>
            StatusText,
            /// <summary>AddView Note column </summary>
            AddViewNote,
            /// <summary>Notify link column (hidden)</summary>
            Notify,
            ///<summary> COI Status refcode value
            COIRefCodeStatus
        }

        #endregion
    }
}